const db = require('../config/DBconnector');
const { DataTypes } = require('sequelize');
const { numberGetter, timeGetter } = require('../utils/ModelUtil');
const Trade = require('./Trade');
const { OrderStatus } = require('../constants/DbEnum');

const name = 'Order';

const fields = {
  username: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  orderType: {
    type: DataTypes.STRING(12),
    allowNull: false,
  },
  baseCoinType: {
    // USD, BTC, ETH, BCH...
    type: DataTypes.STRING(10),
    allowNull: false,
  },
  baseCoinAddress: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  baseCoinAmount: {
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0.01 },
    get: numberGetter(),
  },
  counterCoinType: {
    // USD, BTC, ETH, BCH...
    type: DataTypes.STRING(10),
    allowNull: false,
  },
  counterCoinAddress: {
    type: DataTypes.STRING,
    defaultValue: '',
  },
  counterCoinAmount: {
    type: DataTypes.DECIMAL(40, 20),
    validate: { min: 0.0001 },
    get: numberGetter(),
  },
  price: {
    // counterCoinAmount * price = baseCoinAmount
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0.01 },
    get: numberGetter(),
  },
  depositPrice: {
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0 },
    defaultValue: 0,
    get: numberGetter(),
  },
  currentBaseCoinAmount: {
    type: DataTypes.DECIMAL(40, 20),
    allowNull: false,
    validate: { min: 0 },
    get: numberGetter(),
  },
  status: {
    // PENDING, CANCELED, EXPIRED, COMPLETED, HISTORICAL...
    type: DataTypes.STRING(12),
    allowNull: false,
    defaultValue: OrderStatus.PENDING,
  },
  expiredTimestamp: {
    type: DataTypes.DATE,
    defaultValue: () => {
      return Date.now() + 24 * 60 * 60 * 1000;
    },
    get: timeGetter(),
  },
  historicalTradeCount: {
    type: DataTypes.INTEGER,
    allowNull: false,
    defaultValue: 0,
    get: numberGetter(),
  },
};

const options = {
  getterMethods: {
    doneBaseCoinAmount() {
      return this.baseCoinAmount - this.currentBaseCoinAmount;
    },
    Trades() {
      let trades = new Array();
      if (this.buyTrades) {
        trades.push(...this.buyTrades);
      }
      if (this.sellTrades) {
        trades.push(...this.sellTrades);
      }
      return trades;
    },
  },
};

const model = db.define(name, fields, options);

model.hasMany(Trade, { as: 'buyTrades', foreignKey: 'buyOrderId', hook: true });
model.hasMany(Trade, { as: 'sellTrades', foreignKey: 'sellOrderId', hook: true });

module.exports = model;
